#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fs.h"
#include "user.h"

// 待查找目录 待查找文件名 当前路径下索引的文件名
void find(const char *path, const char *filename, const char *cur_filename)
{
    // 文件路径、待拼接字符指针
    char buf[512], *p;  
    // 待打开的文件
    int fd;        
    // 目录结构  
    struct dirent de;
    // 文件信息   
    struct stat st;     

    // 打开文件
    if ((fd = open(path, 0)) < 0) {
        printf("find: cannot %s\n", path);
        return;
    }
    // 获取文件信息
    if(fstat(fd, &st) < 0){
        printf("find: cannot stat %s\n", path);
        close(fd);
        return;
    }
    // 判断类型
    switch (st.type) {
        // 若是文件，判断该文件名是否和要查找的文件名相同
        case T_FILE:
            // 将当前路径下对应的文件名和要查找的文件名相比 
            if (strcmp(cur_filename, filename) == 0)
                printf("%s\n", path);
        break;
        // 若是目录，则在目录中递归查找文件
        case T_DIR:
            // 判断path是否过长  原路径长度 + 反斜杠 + 最长文件名 + 末尾的0 
            if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
                printf("find: path too long\n");
                break;
            }        

            // 拼接路径 先加上反斜杠
            strcpy(buf, path);
            p = buf + strlen(buf);
            *p++ = '/';
            
            // 扫描目录中的每一个文件
            while (read(fd, &de, sizeof(de)) == sizeof(de)){
                // 跳过第0个inode
                if (de.inum == 0)
                    continue;
                // 跳过 . 和 ..
                if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)
                    continue;
                // 把当前扫描到的目录名或者文件名拼接到路径后 为啥不是sizeof(de.name)
                memmove(p, de.name, DIRSIZ);    
                // 添加字符串结束符
                p[DIRSIZ] = 0;

                // 此时的buf已经是拼接好了的路径 递归进入路径继续find                  
                find(buf, filename, p);        
            }
        break;
    }
    // 关闭文件
    close(fd);
}


int main(int argc, char *argv[]){
    //检查参数数量是否正确
    if (argc != 3) {
        printf("find needs 2 argument!\n"); 
        printf("The correct usage is \"find <dir> <filename>\"\n");
        exit(-1);
    }
    
    // 判断第一个参数是否是目录路径
    if(argv[1][0] != '.' && argv[1][0] != '\\'){
        printf("the first argument should be a directory\n"); 
        printf("The correct usage is \"find <dir> <filename>\"\n");
        exit(-1);        
    }

    // 递归find
    find(argv[1], argv[2], (void*)0);
    exit(0);
}